// msg_type:user_msg,

// typedef struct header{
//     unsigned short msg_len;
// 	unsigned char msg_type;
// 	char src_name[10];
// 	char dst_name[10];
// 	char msg[1300];
// }

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>

#define FAILED 1
#define SUCCESS 2

#define PASSWD_FAILED 3
#define PASSWD_OK 4
#define USER_NOT_EXIST 5
#define USER_ALREADY_EXIST 6
#define ONLINE 7
#define OFFLINE 8

char method[20];
char user_name[20];
char user_passwd[20];

// int error_num = 0;

// typedef struct USER_INFO{
//     int sock;
//     char user_name[20];
// }user_info;

// typedef struct DEVICE_INFO{
//     int sock;
//     char device_name[20];
// }device_info;

// user_info u_info[20];
// device_info d_info[20];

int get_sock_line(int sock, char *buf)
{
    int n = 0, i = 0;
    char c = '\0';
    while(1) {
rd:     n = read(sock, &c, 1);
        if(n > 0) {
            if(c == '\r') {
                n = read(sock, &c, 1);
                if(n > 0 && c == '\n') {
                    buf[i] = '\0';
                    i++;
                    break;
                }
            }
            else {
                if(c == ' ') goto rd; //去掉空格
                buf[i] = c;
                i++;
            }
        }
        else {
            return -1;
        }
    }
    return i;
}

int get_buf_line(char *buf1, char *buf)
{
    int n = 0, i = 0;
    char c = '\0';
    while(1) {
rd:     n = read(sock, &c, 1);
        if(n > 0) {
            if(c == '\r') {
                n = read(sock, &c, 1);
                if(n > 0 && c == '\n') {
                    buf[i] = '\0';
                    i++;
                    break;
                }
            }
            else {
                if(c == ' ') goto rd; //去掉空格
                buf[i] = c;
                i++;
            }
        }
        else {
            return -1;
        }
    }
    return i;
}

int getuser_status()
{
    return ONLINE;
}

int verify_passwd()
{
    return PASSWD_OK;
}

int register()
{
    //add database;
}

int login()
{
    check passwd in database;
    if ok
        add to user list
        return SUCCESS;
    else
        write(ERROR)
        return FAILED;
}

// CONNECT DELETE-DEVICE MESSAGE QUERY

void parse_header(int sock)
{

}

void response_msg(int sock, char *msg)
{

}

void *handle_client(void *data)
{
    int sock,n,i=40;
    char buf[100];
    sock = *((int *)data);
    while(1) {
        //bzero(buf, 100);
        //n = get_line(sock, buf);
        if(-1 == n) {
            close(sock);
            return 0;
        }
        if(strncmp(buf, "REGISTER", 8) == 0) {
           if (FAILED == register()) {
               response_msg("RESPONSE-REGISTER\r\n");
               close(sock);
               return 0;
           }
        }
        else if(strncmp(buf, "LOGIN", 5) == 0) {
            if(FAILED == login()) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
        }
        else if(strncmp(buf, "CONNECT", 9) == 0) {
            if(OFFLINE == getuser_status(sock)) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            if(PASSWD_FAILED == verify_passwd(sock)) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            if(FAILED == connect()) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            response_msg(num_info);
        }
        else if(strncmp(buf, "DELETE-DEVICE", 9) == 0) {
            if(OFFLINE == getuser_status(sock)) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            if(PASSWD_FAILED == verify_passwd(sock)) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            if(FAILED == delete_device()) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            response_msg(num_info);
        }
        else if(strncmp(buf, "MESSAGE", 8) == 0) {
            if(OFFLINE == getuser_status(sock)) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            if(PASSWD_FAILED == verify_passwd(sock)) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            if(FAILED == transmit_message()) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            response_msg(num_info);
        }
        else if(strncmp(buf, "QUERY", 8) == 0) {
            if(OFFLINE == getuser_status(sock)) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            if(PASSWD_FAILED == verify_passwd(sock)) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            if(FAILED == query()) {
                response_msg(error_num);
                close(sock);
                return 0;
            }
            response_msg(num_info);
        }
        else {

        }
    }
    return 0;
}

int main()
{
    // int pid = fork();
    // if(pid > 0)
    //     exit(0);

    int serversock = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == serversock)
    {
        perror("Socket");
        return -1;
    }

    struct sockaddr_in addr,clienaddr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");

    int on = 1;
    setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    if(-1 == bind(serversock, (struct sockaddr *)&addr, sizeof (addr)))
    {
        perror("Bind");
        return -1;
    }

    listen(serversock,100);
    int len = sizeof(clienaddr);

    pthread_t t;
    while(1)
    {
        int  cliensock = accept(serversock, (struct sockaddr *)&clienaddr, &len);

        pthread_create(&t, NULL, handle_client, &cliensock);

    }
}